﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kaidou.Model;
using Kaidou.Persister;
using System.Runtime.CompilerServices;
using System.Threading;
using Kaidou.Util;
using System.Resources;

namespace Kaidou.Bll
{
    public class TRN_ReceiptOrderManager1
    {

        //private static TRN_ReceiptOrderManager1 manager;
        //public static TRN_ReceiptOrderManager1 checkout()
        //{
        //    if (manager == null) manager = new TRN_ReceiptOrderManager1();
        //    return manager;
        //}

        //public static void checkin( TRN_ReceiptOrderManager1 manager) {

        //}

        //public bool receiptOrder(Order order)
        //{
        //    //ステータス変更
        //    order.getJuchu_H().JuchuSts = TrnJuchuh.JUCHU_STATUS_ORDERD;
        //    TRN_Juchu_HPersister dao = new TRN_Juchu_HPersister();
        //    dao.updateJuchu_HForKaidouUser(order.getJuchu_H());

        //    return true;
        //}

        //private static ResourceManager m_ResourceManager;
        /** Singleton Instance */
        private static TRN_ReceiptOrderManager1 instance = new TRN_ReceiptOrderManager1();
        /** 排他処理のためのフラグ */
        private static bool locked = false;

        /** デフォルトコンストラクタ */
        private TRN_ReceiptOrderManager1()
        {
        }

        /**
         * 処理の開始時に Instance を取得し、ロックする
         *
         * @return このクラスの Singleton Instance. 他で使用中のときは５秒間待ってから例外を返す
         * @throws InputErrorException
         */
        public static TRN_ReceiptOrderManager1 checkout()
        {
            try
            {
                for (int i = 0; i < 25; i++)
                {
                    //int j = i+1;
                    //Logger.logWrite(NextSealNoSequencePersister.class.getName(), "D", "待機 " + j + "回目 = " + i*0.5 + "秒経過");
                    if (!locked)
                    {
                        //Logger.logWrite(NextSealNoSequencePersister.class.getName(), "D", "シングルトン取得成功 " + i+1 + "回目 = " + i*0.5 + "秒経過");
                        locked = true;
                        //m_ResourceManager=resourceManager;
                        return instance;
                    }
                    Thread.Sleep(400);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            throw new Exception("InputErrorException");//4300
        }

        /**
         * 処理終了後にロックを解除する
         */
        public static void checkin()
        {
            locked = false;
        }

        /**
         * 注文受付処理を行う.
         * ユーザによる対話処理のみ。TRN_Purch_Seal の insert は行わない。
         *
         * @param data データモデル
         * @return boolean
         */
        [MethodImpl(MethodImplOptions.Synchronized)]
        public bool receiptOrder(Order data, LoginModel loginModel)
        {
            /*
            try {
                sleep(10000);
            } catch (InterruptedException e) {
                throw new InputErrorException(e);
            }
            */

            LogManager.debug("TRN_JuchuManager - receiptOrder - Started");

            if (!locked)
            {
                throw new Exception("The class is not locked.");
            }

            SqlDB con = null;
            bool update = false;
            NextSealNoSequenceModel seqModel = new NextSealNoSequenceModel();
            seqModel.setStart_No(0);

            int initialStartSealNo = 0;
            // シール番号採番モジュールを排他ロック
            NextSealNoSequencePersister seqPer = NextSealNoSequencePersister.checkout();
            //コネクション取得
            con = new SqlDB();
            con.TransBegin();
            try
            {



                //パーシスターを作成
                TRN_Juchu_HPersister perH = new TRN_Juchu_HPersister();
                TRN_Juchu_DPersister perD = new TRN_Juchu_DPersister();
                TRN_Juchu_UketukePersister perU = new TRN_Juchu_UketukePersister();

                TrnJuchuh h = data.getJuchu_H();
                TrnJuchud[] dlist = data.getJuchu_D();
                TrnJuchud[] olddlist = perD.getDetail(h.JuchuNo);

                System.DateTime nowDate = perH.getCurrentDate(con);
                System.DateTime nowTimestamp = nowDate;//perH.getCurrentTimestamp(con);

                //受付処理が済んでいる場合は Exception
                if (perU.checkFinished(con, h.JuchuNo))
                {
                    throw new Exception("checkFinished");
                }

                //注文全体のシール番号の開始値を取得
                seqModel = seqPer.NextvalProcedure(con);
                initialStartSealNo = seqModel.getStart_No();

                //ステータス変更
                h.JuchuSts = TrnJuchuh.JUCHU_STATUS_ORDERD;
                h.FaxErrorFlg = TrnJuchuh.FAX_ERROR_FLAG_OK;

                h.HachuDate = nowDate;
                h.HachuUnionCode = loginModel.Unioncode;
                h.HachuBranchCode = (short)loginModel.Branchcode;
                h.UpdDate = nowTimestamp;
                h.UpdUnionCode = loginModel.Unioncode;
                h.UpdBranchCode = (short)loginModel.Branchcode;
                h.UpdFuncId = "receiptOrder";

                //update
                update = perH.updateJuchu_HForKaidouUser(con, h);

                //見出しデータが存在しない場合は明細に対する処理を行わない
                if (update)
                {
                    int currentStartSealNo = initialStartSealNo;
                    int currentEndSealNo = 0;

                    for (int i = 0; i < dlist.Length; i++)
                    {
                        TrnJuchud d = dlist[i];

                        if (d == null)
                        {
                            perD.delete(con, h.JuchuNo, i + 1);
                            continue;
                        }

                        d.UpdDate = nowTimestamp;
                        d.UpdUnionCode = loginModel.Unioncode;
                        d.UpdBranchCode = (short)loginModel.Branchcode;
                        d.UpdFuncId = "receiptOrder";

                        //明細ごとのシール開始・終了番号をセット
                        d.SealStrNo = System.DateTime.Now.ToString("yy") + currentStartSealNo.ToString("0000000");
                        currentEndSealNo = currentStartSealNo + d.SealQty - 1;
                        d.SealEndNo = System.DateTime.Now.ToString("yy") + currentEndSealNo.ToString("0000000");

                        //次の開始シール番号
                        currentStartSealNo = currentEndSealNo + 1;

                        if (olddlist[i] != null)
                        {
                            update = update & perD.update(con, d);
                        }
                        else
                        {
                            d.RegDate = nowTimestamp;
                            update = update & perD.insert(con, d);
                        }

                        LogManager.debug("TRN_JuchuManager - receiptOrder - updated Juchu-D juchu_no[" + d.Id.JuchuNo + "] juchu_rec_no[" + d.Id.JuchuRecNo + "]");

                        // シール受付明細へレコードを挿入する（夜間バッチがこのレコードを参照する）
                        perU.insert(con, d);
                    }

                    //currentStartSealNo を次のシーケンスにセット
                    seqPer.restartSealNoSequence(con, currentStartSealNo);
                }

                con.TransCommit();
                return update;

            }
            catch (Exception pe)
            {
                //rollback
                try
                {
                    con.TransRollback();

                    //Seal No Sequence を rollback   ----zhou 20121210
                    //con.TransBegin();
                    //seqPer.restartSealNoSequence(con, initialStartSealNo);
                    //con.TransCommit();
                }
                catch (Exception e)
                {
                    LogManager.error("TRN_JuchuManager - receiptOrder" + e.ToString());
                }

                LogManager.error("TRN_JuchuManager - receiptOrder" + pe.ToString());
                throw pe;
            }
            finally
            {
                try
                {
                    // 採番排他ロックを解除
                    NextSealNoSequencePersister.checkin();
                    seqPer = null;


                }
                catch (Exception e)
                {
                    LogManager.fatal("TRN_JuchuManager - receiptOrder - finally - autocommit on" + e.ToString());
                }
                try
                {
                    //release connection
                    con.Close();
                }
                catch (Exception e)
                {
                    LogManager.fatal("TRN_JuchuManager - receiptOrder - finally" + e.ToString());
                }
            }
        }

    }
}
